﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Wilke.Interactive.Drone.Control;
using Wilke.Interactive.Drone.Control.Enumerations;
using System.Threading;
using Wilke.Interactive.Drone.InputProviders;
using Wilke.Interactive.Drone.Contracts;
using Wilke.Interactive.Drone.Extensions;

namespace Wilke.Interactive.Drone.Simple
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private DroneController droneController;
        private IInputProvider inputProvider;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void buttonConnect_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                listBoxTraceMessages.Items.Clear();

                #region Initialize DroneControllerConfiguration

                DroneControllerConfiguration droneControllerConfiguration = new DroneControllerConfiguration();

                droneControllerConfiguration.NetworkIdentifier = textBoxNetworkId.Text;
                droneControllerConfiguration.EnableNavigationDataThread = true;
                droneControllerConfiguration.EnableVideoStreamThread = true;
                droneControllerConfiguration.EnableATCommandThread = true;
                droneControllerConfiguration.EnableControlInfoThread = true;
                droneControllerConfiguration.VideoFilePath = textBoxPath.Text;
                droneControllerConfiguration.PictureFilePath = textBoxPath.Text;
                droneControllerConfiguration.EnableATCommandSimulation = false;

                #endregion

                #region Initialize DroneController

                droneController = new DroneController(droneControllerConfiguration);

                droneController.TraceNotificationLevel = TraceNotificationLevel.Verbose;
                droneController.OnNotifyTraceMessage += new EventHandler<TraceNotificationEventArgs>(droneController_OnNotifyTraceMessage);
                droneController.OnNotifyVideoMessage += new EventHandler<VideoNotificationEventArgs>(droneController_OnNotifyVideoMessage);
                droneController.OnNotifyDroneInfoMessage += new EventHandler<DroneInfoNotificationEventArgs>(droneController_OnNotifyDroneInfoMessage);
                droneController.OnConnectionStatusChanged += new EventHandler<ConnectionStatusChangedEventArgs>(droneController_OnConnectionStatusChanged);

                #endregion

                #region Connect DroneController

                droneController.Connect();

                #endregion

                buttonConnect.IsEnabled = false;
                buttonDisconnect.IsEnabled = true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        void droneController_OnConnectionStatusChanged(object sender, ConnectionStatusChangedEventArgs e)
        {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(new Action<object, ConnectionStatusChangedEventArgs>(droneController_OnConnectionStatusChanged), sender, e);
            }
            else
            {
                labelStatus.Content = e.ConnectionStatus.ToString();
            }
        }

        void droneController_OnNotifyDroneInfoMessage(object sender, DroneInfoNotificationEventArgs e)
        {
            
        }

        void droneController_OnNotifyVideoMessage(object sender, VideoNotificationEventArgs e)
        {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(new Action<object, VideoNotificationEventArgs>(droneController_OnNotifyVideoMessage), sender, e);
            }
            else
            {
                image.Source = e.CurrentImage;
            }
        }

        void droneController_OnNotifyTraceMessage(object sender, TraceNotificationEventArgs e)
        {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(new Action<object, TraceNotificationEventArgs>(droneController_OnNotifyTraceMessage), sender, e);
            }
            else
            {
                int index = listBoxTraceMessages.Items.Add(e.NotificationMessage);
                listBoxTraceMessages.ScrollIntoView(listBoxTraceMessages.Items[index]);
            }
        }
     
        private void buttonDisconnect_Click(object sender, RoutedEventArgs e)
        {
            droneController.Disconnect();

            buttonConnect.IsEnabled = true;
            buttonDisconnect.IsEnabled = false;
        }

        private void buttonTakeOff_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null && droneController.ConnectionStatus == ConnectionStatus.Open)
            {
                droneController.SetFlatTrim();
                droneController.StartEngines();
            }
        }

        private void buttonLand_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null)
            {
                droneController.StopEngines();
            }
        }

        private void buttonFlatTrim_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null)
            {
                droneController.SetFlatTrim();
            }
        }

        private void buttonReset_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null)
            {
                droneController.StartReset();

                Thread.Sleep(20);

                droneController.StopReset();
            }
        }
     
        private void sliderPitch_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            droneController.SetFlightParameters(0, (float)sliderPitch.Value, 0, 0);
        }

        private void sliderRoll_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            droneController.SetFlightParameters((float)sliderRoll.Value, 0, 0, 0);
        }

        private void sliderHeight_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            droneController.SetFlightParameters(0, 0, (float)sliderHeight.Value, 0);
        }

        private void sliderYaw_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            droneController.SetFlightParameters(0, 0, 0, (float)sliderYaw.Value);
        }

        private void buttonStartVideo_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null && droneController.ConnectionStatus == ConnectionStatus.Open)
            {
                droneController.StartRecordVideo();
                buttonStartVideo.IsEnabled = false;
                buttonStopVideo.IsEnabled = true;
            }
        }

        private void buttonStopVideo_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null && droneController.ConnectionStatus == ConnectionStatus.Open)
            {
                droneController.StopRecordVideo();
                buttonStartVideo.IsEnabled = true;
                buttonStopVideo.IsEnabled = false;
            }
        }

        private void buttonTakePicture_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null && droneController.ConnectionStatus == ConnectionStatus.Open)
            {
                droneController.TakePicture();
            }
        }

        private void buttonPlayLedAnimation_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null && droneController.ConnectionStatus == ConnectionStatus.Open)
            {
                droneController.PlayLedAnimation(LedAnimation.BlinkGreen, 2, 5);
            }
        }

        private void buttonWiimoteActivate_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null && droneController.ConnectionStatus == ConnectionStatus.Open)
            {
                inputProvider = new WiimoteInputProvider(droneController);
                inputProvider.Initialize(droneController.RollThrottleValue, droneController.PitchThrottleValue, droneController.HeightThrottleValue, droneController.YawThrottleValue);
            }
        }

        private void buttonWiimoteDeactivate_Click(object sender, RoutedEventArgs e)
        {
            if (inputProvider != null)
            {
                inputProvider.Dispose();
                inputProvider = null;
            }
        }

        private void buttonPathDesigner_Click(object sender, RoutedEventArgs e)
        {
            if (droneController != null && droneController.ConnectionStatus == ConnectionStatus.Open)
            {
                inputProvider = new AssistInputProvider(droneController);
                inputProvider.Initialize(droneController.RollThrottleValue, droneController.PitchThrottleValue, droneController.HeightThrottleValue, droneController.YawThrottleValue);

                PathDesigner pathDesigner = new PathDesigner(droneController);
                pathDesigner.ShowDialog();

                //Switch back to the selected inputprovider
                inputProvider = new WiimoteInputProvider(droneController);
                inputProvider.Initialize(droneController.RollThrottleValue, droneController.PitchThrottleValue, droneController.HeightThrottleValue, droneController.YawThrottleValue);
            }
            else
            {
                MessageBox.Show("This feature is only available if a connection is made with the ARDrone.");
            }
        }
    }
}
